package com.xinyi.reactivemvvm.sources.repository;

import androidx.annotation.WorkerThread;

import com.xinyi.httpdemo.model.ResponseData;
import com.xinyi.reactivemvvm.model.Resource;

import java.util.concurrent.Callable;


/**
 * @author 杨耿雷
 * @date 2024/9/23 22:21
 * @description 数据仓库基类，用于统一处理接口回调的数据流向
 */
public class BaseRepository {

    /**
     * 远程API调用方法。
     * 该方法同步执行远程API请求，并将其结果通过 Flow 机制发射不同状态的数据流，包括加载中、成功和失败的状态。
     *
     * @param apiCall    API调用的逻辑，传入的Callable会返回ResponseData对象，表示API请求结果。
     * @param <T>        API调用返回的数据类型。
     * @return FlowCollect<Resource<T>> 返回包含资源状态的数据流，可能是加载中、成功或失败。
     *
     * <p>
     * FlowCollect对象会收集三个不同的状态
     * @see Resource.Loading 加载中状态
     * @see Resource.Success 请求成功状态 （包含成功的数据）
     * @see Resource.Fail 请求失败状态 （包含错误信息或异常）
     */
    @SuppressWarnings("unchecked")
    @WorkerThread
    public <T> FlowCollect<Resource<T>> safeRemoteApiCall(Callable<ResponseData> apiCall) {
        return emitter -> {
            emitter.emit(new Resource.Loading<>());
            try {
                // 调用API并获得ResponseData对象
                ResponseData responseData = apiCall.call();

                // 检查ResponseData是否成功
                if (responseData.isSuccess() && (responseData.getCode() == 0 || responseData.getCode() == 200)) {
                    // 请求成功，返回成功状态和数据
                    emitter.emit(new Resource.Success<>((T) responseData.getData()));
                } else {
                    // 请求失败，返回失败状态和错误信息
                    emitter.emit(new Resource.Fail<>(new Exception(responseData.getMessage())));
                }
            } catch (Exception e) {
                // 请求异常，返回失败状态和异常信息
                emitter.emit(new Resource.Fail<>(e));
            }
        };
    }

    /**
     * @author 杨耿雷
     * @date 2024/9/24 16:22
     * @description 模拟 Kotlin协程里的 Flow 的数据收集接口
     * @see kotlinx.coroutines.flow.Flow
     */
    public interface FlowCollect<T> {

        /**
         * 收集数据
         * @param emitter 数据发射器
         */
        void collect(FlowEmitter<T> emitter);
    }

    /**
     * @author 杨耿雷
     * @date 2024/9/24 16:20
     * @description 模拟 Kotlin协程库里的 FlowCollector 的数据发射接口
     * @see kotlinx.coroutines.flow.FlowCollector
     */
    public interface FlowEmitter<T> {

        /**
         * 发射数据
         * @param value 数据
         */
        void emit(T value);
    }
}